import {
  Component,
  ViewEncapsulation,
  ChangeDetectionStrategy,
  Input,
  TemplateRef,
  ElementRef,
  ChangeDetectorRef,
  Output,
  EventEmitter,
  OnInit,
} from '@angular/core';
import { trigger, state, style, transition, animate, AnimationEvent, group } from '@angular/animations';
import { InputBoolean, TypeUtils } from '../core/api';
import { MotionDuration, MotionFunc } from '../core/animation/api';

@Component({
  selector: 'lv-alert, [lv-alert]',
  exportAs: 'lvAlert',
  templateUrl: './alert.component.html',
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush,
  host: {
    '[class.lv-alert]': 'true',
    '[class.lv-alert-success]': "lvType === 'success'",
    '[class.lv-alert-error]': "lvType === 'error'",
    '[class.lv-alert-warning]': "lvType === 'warning'",
    '[class.lv-alert-information]': "lvType === 'info'",
    '[@animAlert]': '_animate',
    '(@animAlert.done)': 'onAnimationDone($event)',
  },
  animations: [
    trigger('animAlert', [
      state(
        'void',
        style({
          opacity: 1,
          display: '*',
        }),
      ),
      state(
        'hide',
        style({
          opacity: 0,
          display: 'none',
          height: '0',
          paddingTop: '0',
          paddingBottom: '0',
          marginTop: '0',
          marginBottom: '0',
        }),
      ),
      state(
        'show',
        style({
          opacity: 1,
          display: '*',
          height: '*',
          paddingTop: '*',
          paddingBottom: '*',
          marginTop: '*',
          marginBottom: '*',
        }),
      ),
      transition('show => hide', [
        group([
          animate(
            `${MotionDuration.MD} ${MotionFunc.EASE}`,
            style({
              height: '0',
              paddingTop: '0',
              paddingBottom: '0',
              marginTop: '0',
              marginBottom: '0',
            }),
          ),
          animate(
            `${MotionDuration.MD} ${MotionFunc.EASE_IN_OUT}`,
            style({
              opacity: 0,
            }),
          ),
        ]),
      ]),
      transition('hide => show', [
        group([
          animate(
            `${MotionDuration.MD} ${MotionFunc.EASE}`,
            style({
              height: '*',
              paddingTop: '*',
              paddingBottom: '*',
              marginTop: '*',
              marginBottom: '*',
            }),
          ),
          animate(
            `${MotionDuration.MD} ${MotionFunc.EASE_IN_OUT}`,
            style({
              opacity: 1,
            }),
          ),
        ]),
      ]),
    ]),
    trigger('iconContent', [
      state(
        'void',
        style({
          opacity: 1,
          height: '*',
        }),
      ),
      state(
        'hide',
        style({
          opacity: 0,
          height: 'calc(100% / 2)',
        }),
      ),
      state(
        'show',
        style({
          opacity: 1,
          height: '*',
        }),
      ),
      transition('show => hide', [
        group([
          animate(
            `${MotionDuration.MD} ${MotionFunc.EASE}`,
            style({
              height: 'calc(100% / 2)',
            }),
          ),
          animate(
            `${MotionDuration.MD} ${MotionFunc.EASE_IN_OUT}`,
            style({
              opacity: 0,
            }),
          ),
        ]),
      ]),
      transition('hide => show', [
        group([
          animate(
            `${MotionDuration.MD} ${MotionFunc.EASE}`,
            style({
              height: '*',
            }),
          ),
          animate(
            `${MotionDuration.MD} ${MotionFunc.EASE_IN_OUT}`,
            style({
              opacity: 1,
            }),
          ),
        ]),
      ]),
    ]),
  ],
})
export class AlertComponent implements OnInit {
  @Input() lvAction: TemplateRef<void>;

  @Input() @InputBoolean() lvClosable = true;

  @Input() @InputBoolean() lvShowIcon = true;

  @Input() lvIcon: string | TemplateRef<void> = null;

  @Output() lvClose: EventEmitter<any> = new EventEmitter();

  @Input() lvType: 'success' | 'info' | 'warning' | 'error' | 'default' = 'default';

  public _animate;
  public _animationState;
  public typeUtils = TypeUtils;
  public icons = {
    success: 'lv-icon-status-succeed',
    info: 'lv-icon-status-info',
    warning: 'lv-icon-status-warning-info',
    error: 'lv-icon-status-error',
    default: 'lv-icon-status-info',
  };

  constructor(
    public cdr: ChangeDetectorRef,
    public el: ElementRef,
  ) {}

  close(): void {
    this._animate = 'hide';
    this._animationState = 'hide';
  }

  ngOnInit(): void {
    this._animate = 'show';
    this._animationState = 'show';
  }

  /**
   * listen animation(done)
   */
  public onAnimationDone(event: AnimationEvent): void {
    if (event.triggerName === 'animAlert' && event.fromState === 'show' && event.toState === 'hide') {
      this.lvClose.emit();
    }
  }
}
